<?php

namespace support;

/**
 * PDF图片提取类
 * 用于从PDF文件中提取所有图片
 */
class PdfToImg
{
    /**
     * @var string PDF文件路径
     */
    protected $pdfPath;
    
    /**
     * @var string 输出目录路径
     */
    protected $outputDir;
    
    /**
     * @var array 支持的图片格式
     */
    protected $supportedFormats = ['jpeg', 'jpg', 'png', 'gif'];

    /**
     * 构造函数
     * 
     * @param string $pdfPath PDF文件路径
     * @param string $outputDir 图片输出目录
     */
    public function __construct(string $pdfPath, string $outputDir = null)
    {
        if (!file_exists($pdfPath)) {
            throw new \InvalidArgumentException("PDF文件不存在: {$pdfPath}");
        }
        
        $this->pdfPath = $pdfPath;
        $this->outputDir = $outputDir ?? dirname($pdfPath) . DIRECTORY_SEPARATOR . 'extracted_images';
        
        // 确保输出目录存在
        if (!is_dir($this->outputDir)) {
            if (!mkdir($this->outputDir, 0755, true)) {
                throw new \RuntimeException("无法创建输出目录: {$this->outputDir}");
            }
        }
    }

    /**
     * 使用Imagick扩展提取PDF中的图片
     * 
     * @return array 提取的图片文件路径列表
     */
    public function extractWithImagick()
    {
        if (!extension_loaded('imagick')) {
            throw new \RuntimeException('需要安装Imagick扩展');
        }
        
        $extractedFiles = [];
        
        try {
            // 设置分辨率以获得更好的图像质量
            $imagick = new \Imagick();
            $imagick->setResolution(300, 300);
            $imagick->readImage($this->pdfPath);
            
            // 正确迭代所有页面
            $numPages = $imagick->getNumberImages();
            for ($i = 0; $i < $numPages; $i++) {
                // 设置迭代器索引到当前页
                $imagick->setIteratorIndex($i);
                // 获取当前页的Imagick对象
                $currentPage = $imagick->current();
                
                $images = $this->extractImagesFromPage($currentPage, $i);
                if (!empty($images)) {
                    $extractedFiles = array_merge($extractedFiles, $images);
                }
            }
        } catch (\ImagickException $e) {
            throw new \RuntimeException("提取图片失败: " . $e->getMessage());
        }
        
        return $extractedFiles;
    }

    /**
     * 从PDF页面提取图片
     * 
     * @param \Imagick $pageImage 页面的Imagick对象
     * @param int $pageIndex 页码
     * @return array 提取的图片路径
     */
    protected function extractImagesFromPage(\Imagick $pageImage, int $pageIndex)
    {
        $extractedFiles = [];
        
        // 尝试提取图像对象
        $images = $pageImage->getImagesBlob();
        if ($images) {
            $tempFile = $this->outputDir . DIRECTORY_SEPARATOR . "page_{$pageIndex}_temp.dat";
            file_put_contents($tempFile, $images);
            
            // 识别图片类型并保存
            $finfo = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->file($tempFile);
            
            if (strpos($mimeType, 'image/') === 0) {
                $ext = str_replace('image/', '', $mimeType);
                if (in_array($ext, $this->supportedFormats)) {
                    $outputPath = $this->outputDir . DIRECTORY_SEPARATOR . "img_p{$pageIndex}." . $ext;
                    rename($tempFile, $outputPath);
                    $extractedFiles[] = $outputPath;
                }
            }
            
            // 清理临时文件
            if (file_exists($tempFile)) {
                unlink($tempFile);
            }
        }
        
        return $extractedFiles;
    }
    
    /**
     * 使用Poppler工具提取PDF中的图片(需要系统安装pdfimages)
     *
     * @return array 提取的图片文件路径列表
     */
    public function extractWithPdfImages()
    {
        $outputPrefix = $this->outputDir . DIRECTORY_SEPARATOR . 'img';
        $command = "pdfimages -all \"{$this->pdfPath}\" \"{$outputPrefix}\"";

        exec($command, $output, $returnCode);

        if ($returnCode !== 0) {
            throw new \RuntimeException("提取图片失败，请确保已安装pdfimages工具");
        }

        // 获取生成的所有文件
        $extractedFiles = glob($this->outputDir . DIRECTORY_SEPARATOR . 'img-*');
        return $extractedFiles;
    }

    /**
     * 使用pdftoppm工具将PDF转换为高质量图像(需要系统安装pdftoppm)
     *
     * @param string $format 输出格式 (png, jpg, jpeg, tiff)
     * @param int $dpi 输出分辨率DPI，越高质量越好
     * @return array 生成的图片文件路径列表
     */
    public function extractWithPdftoPpm(string $format = 'png', int $dpi = 300)
    {
        // 验证格式
        $validFormats = ['png', 'jpg', 'jpeg', 'tiff'];
        if (!in_array(strtolower($format), $validFormats)) {
            throw new \InvalidArgumentException("不支持的图像格式: {$format}，支持的格式有: " . implode(', ', $validFormats));
        }

        // 构建命令
        $outputPrefix = $this->outputDir . DIRECTORY_SEPARATOR . 'page';
        $command = "pdftoppm -{$format} -r {$dpi} \"{$this->pdfPath}\" \"{$outputPrefix}\"";

        exec($command, $output, $returnCode);

        if ($returnCode !== 0) {
            throw new \RuntimeException("转换PDF为图像失败，请确保已安装pdftoppm工具");
        }

        // 获取生成的所有图像文件
        $extractedFiles = glob($this->outputDir . DIRECTORY_SEPARATOR . "page-*." . $format);

        return $extractedFiles;
    }

    /**
     * 主提取方法，自动选择可用的提取方式
     *
     * @return array 提取的图片文件路径列表
     */
    public function extract()
    {
        // 首先尝试使用Imagick
        if (extension_loaded('imagick')) {
            return $this->extractWithImagick();
        }

        // 检查pdftoppm是否可用（首选）
        exec('pdftoppm -v', $output, $returnCode);
        if ($returnCode === 0) {
            return $this->extractWithPdftoPpm('png', 300); // 使用PNG格式，300 DPI
        }

        // 如果pdftoppm不可用，尝试使用pdfimages
        exec('pdfimages --version', $output, $returnCode);
        if ($returnCode === 0) {
            return $this->extractWithPdfImages();
        }

        throw new \RuntimeException('无可用的PDF图像提取工具，请安装Imagick扩展、pdftoppm或Poppler-utils');
    }
    
    /**
     * 获取输出目录路径
     * 
     * @return string
     */
    public function getOutputDir()
    {
        return $this->outputDir;
    }

    /**
     * 清理输出目录中的所有文件
     *
     * @return bool 清理成功返回true，否则返回false
     */
    public function clear()
    {
        if (!is_dir($this->outputDir)) {
            return true; // 目录不存在则视为已清理
        }
        
        $success = true;
        $files = glob($this->outputDir . DIRECTORY_SEPARATOR . '*');
        
        foreach ($files as $file) {
            if (is_file($file)) {
                if (!unlink($file)) {
                    $success = false;
                }
            }
        }
        
        return $success;
    }
}